package com.gear2cam.official; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.hardware.Camera; import android.hardware.SensorManager; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.LayoutInflater; import android.view.OrientationEventListener; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.LinearLayout; import com.commonsware.cwac.camera.CameraFragment; import com.commonsware.cwac.camera.CameraView; import com.commonsware.cwac.camera.PictureTransaction; import com.commonsware.cwac.camera.SimpleCameraHost; import com.gear2cam.official.R; import com.gear2cam.official.services.CameraProviderService; import com.gear2cam.official.services.Gear2camProviderConnection; import com.gear2cam.official.services.Intents; import java.io.File; import java.util.List; /** * Created by sent.ly on 13/5/14. */ public class ViewFinderFragment extends CameraFragment { private static final String TAG = "ViewFinderFragment"; private BroadcastReceiver clickReceiver; private BroadcastReceiver flashModeReceiver; private String flashMode = Camera.Parameters.FLASH_MODE_AUTO; CameraView cameraView; private static final String KEY_USE_FFC= "com.gear2cam.USE_FFC"; /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @return A new instance of fragment ViewFinderFragment. */ // TODO: Rename and change types and number of parameters public static ViewFinderFragment newInstance(boolean useFFC) { ViewFinderFragment fragment = new ViewFinderFragment(); Bundle args=new Bundle(); args.putBoolean(KEY_USE_FFC, useFFC); fragment.setArguments(args); return fragment; } ViewFinderCameraHost host; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); host = new ViewFinderCameraHost(getActivity()); SimpleCameraHost.Builder builder= new SimpleCameraHost.Builder(host); setHost(builder.useFullBleedPreview(false).build()); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { cameraView = (CameraView) super.onCreateView(inflater,container,savedInstanceState); LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.fragment_viewfinder, container, false); ((ViewGroup)rootView.findViewById(R.id.camera)).addView(cameraView); clickReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { takePicture(); } catch (Exception ex) { } } }; IntentFilter filter = new IntentFilter(Intents.INTENT_CLICK); this.getActivity().registerReceiver(clickReceiver, filter); flashModeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int mode = intent.getIntExtra(Intents.EXTRA_FLASH_MODE, 0); switch (mode) { case 0: flashMode = Camera.Parameters.FLASH_MODE_AUTO; break; case 1: flashMode = Camera.Parameters.FLASH_MODE_OFF; break; case 2: flashMode = Camera.Parameters.FLASH_MODE_ON; break; } } }; filter = new IntentFilter(Intents.INTENT_FLASH_MODE); this.getActivity().registerReceiver(flashModeReceiver, filter); host.start(); return rootView; } @Override public void onDestroyView() { getActivity().unregisterReceiver(clickReceiver); getActivity().unregisterReceiver(flashModeReceiver); ViewFinderCameraHost host = (ViewFinderCameraHost) getHost(); host.destroy(); super.onDestroyView(); } public class ViewFinderCameraHost extends SimpleCameraHost { OrientationEventListener myOrientationEventListener; @Override public boolean useFrontFacingCamera() { if (getArguments() == null) { return(false); } return(getArguments().getBoolean(KEY_USE_FFC)); } @Override public Camera.ShutterCallback getShutterCallback() { return new Camera.ShutterCallback() { @Override public void onShutter() { } }; } private int currentOrientation = 0; int angle = 0; public void start() { // View is now attached myOrientationEventListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) { @Override public void onOrientationChanged(int orientation) { if(deviceDefault == -1) { deviceDefault = getDeviceDefaultOrientation(); } try { Quadrant q = new Quadrant(orientation, deviceDefault); int newOrientation = q.getOrientation(); angle = q.getRotation(); if(newOrientation != 0 && newOrientation != currentOrientation) { Log.d(TAG, (useFrontFacingCamera() ? "FRONT" : "BACK") + ", " + newOrientation); currentOrientation = newOrientation; } } catch (Exception ex) { Log.e(TAG, "Orientation exception", ex); } } }; myOrientationEventListener.enable(); } public void destroy() { myOrientationEventListener.disable(); } private Context context; int deviceDefault = -1; public int getDeviceDefaultOrientation() { WindowManager windowManager = (WindowManager) context.getSystemService(context.WINDOW_SERVICE); Configuration config = getResources().getConfiguration(); int rotation = windowManager.getDefaultDisplay().getRotation(); if ( ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && config.orientation == Configuration.ORIENTATION_LANDSCAPE) || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && config.orientation == Configuration.ORIENTATION_PORTRAIT)) { return Configuration.ORIENTATION_LANDSCAPE; } else { return Configuration.ORIENTATION_PORTRAIT; } } public ViewFinderCameraHost(Context _ctxt) { super(_ctxt); context = _ctxt; } @Override protected File getPhotoDirectory() { File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DCIM), "Gear2cam"); if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d(TAG, "failed to create directory"); return null; } } return mediaStorageDir; } File lastPhoto; @Override protected File getPhotoPath() { synchronized (context) { lastPhoto = super.getPhotoPath(); return lastPhoto; } } @Override public void saveImage(PictureTransaction xact, byte[] frame) { synchronized (context) { super.saveImage(xact, frame); String base64 = FacebookHelper.getWatchPreview(lastPhoto.getAbsolutePath()); try { //Create a Parse Analytics event AppAnalytics.trackAppEvent("click"); if(CameraProviderService.getCurrentConnection() != null) { CameraProviderService.getCurrentConnection().sendClicked(); } } catch (Exception ex) { //Should not fail if sound cannot be played } //Tell connection about the file if(CameraProviderService.getCurrentConnection() != null) { CameraProviderService.getCurrentConnection().sendClicked(lastPhoto.getAbsolutePath(), base64); } } } private double aspectRatio = 1.33; private double tolerance = 0.0034; public Camera.Size getBestPreviewSize(List<Camera.Size> mSupportedPreviewSizes) { //Minimum preview size with specified aspect ratio int index = 0; int width = Integer.MAX_VALUE; for(int i=0; i<mSupportedPreviewSizes.size(); i++) { Camera.Size test = mSupportedPreviewSizes.get(i); if (test.width >= 320 && test.width < width && ((double) test.width / (double) test.height - aspectRatio) <= tolerance) { width = test.width; index = i; } } return mSupportedPreviewSizes.get(index); } public Camera.Size getBestPictureSize(List<Camera.Size> mSupportedPictureSize) { //Maximum picture size with given aspect ratio int index = 0; int res = 0; for(int i=0; i<mSupportedPictureSize.size(); i++) { Camera.Size test = mSupportedPictureSize.get(i); if(test.width * test.height > res && ((double) test.width / (double) test.height - aspectRatio) <= tolerance) { res = test.width * test.height; index = i; } } return mSupportedPictureSize.get(index); } @Override public Camera.Size getPreviewSize(int displayOrientation, int width, int height, Camera.Parameters parameters) { return getBestPreviewSize(parameters.getSupportedPreviewSizes()); } @Override public Camera.Size getPictureSize(PictureTransaction xact, Camera.Parameters parameters) { return getBestPictureSize(parameters.getSupportedPictureSizes()); } boolean shutterSoundOff = false; @Override public Camera.Parameters adjustPreviewParameters(Camera.Parameters parameters) { List<String> focusModes = parameters.getSupportedFocusModes(); if(focusModes != null) { if(focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else if(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } else if(focusModes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY); } } if(!shutterSoundOff) { String locale = context.getResources().getConfiguration().locale.getCountry(); if(!locale.equals("JP")) { Camera cam = cameraView.getCamera(); if(cam != null) { cam.enableShutterSound(false); } } shutterSoundOff = true; } if(useFrontFacingCamera()) { parameters.setRecordingHint(false); } return parameters; } @Override public Camera.Parameters adjustPictureParameters(PictureTransaction xact, Camera.Parameters parameters) { List<String> focusModes = parameters.getSupportedFocusModes(); if(focusModes != null) { if(focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else if(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } else if(focusModes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY); } } List<String> flashModes = parameters.getSupportedFlashModes(); if(!useFrontFacingCamera()) { if(flashModes != null) { if(flashModes.contains(flashMode)) { parameters.setFlashMode(flashMode); } else if(flashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)) { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); } else if(flashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); } } } else { if(flashModes != null && flashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); } } return parameters; } @Override public float maxPictureCleanupHeapUsage() { return 0.0f; } @Override public void onPreviewFrame(byte [] rawData, Camera camera) { int w = camera.getParameters().getPreviewSize().width; int h = camera.getParameters().getPreviewSize().height; int format = camera.getParameters().getPreviewFormat(); Gear2camProviderConnection.setCurrentFrame(rawData, angle, w, h, format, useFrontFacingCamera()); } } }